From b9d83543835632073f3075f10a035de2db27cb19 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 19 Apr 2006 18:43:39 +0100 Subject: [PATCH] Clean up the xenoprofile hypercall interface. Signed-off-by: Jose Renato Santos --- .../arch/i386/oprofile/xenoprof.c | 138 ++++++++++++------ .../include/asm-i386/mach-xen/asm/hypercall.h | 4 +- xen/arch/x86/oprofile/xenoprof.c | 122 ++++++++++------ xen/arch/x86/x86_32/entry.S | 2 +- xen/arch/x86/x86_64/entry.S | 2 +- xen/include/public/xenoprof.h | 54 ++++--- 6 files changed, 205 insertions(+), 117 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c index f5184a2c0c..bcfdc23e74 100644 --- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c @@ -35,8 +35,9 @@ static void xenoprof_stop(void); void * vm_map_xen_pages(unsigned long maddr, int vm_size, pgprot_t prot); static int xenoprof_enabled = 0; -static int num_events = 0; +static unsigned int num_events = 0; static int is_primary = 0; +static int active_defined; /* sample buffers shared with Xen */ xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS]; @@ -106,7 +107,7 @@ static irqreturn_t xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs) { int head, tail, size; - xenoprof_buf_t * buf; + struct xenoprof_buf * buf; int cpu; cpu = smp_processor_id(); @@ -196,28 +197,49 @@ static int bind_virq(void) static int xenoprof_setup(void) { int ret; + int i; ret = bind_virq(); if (ret) return ret; if (is_primary) { - ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, - (unsigned long)NULL, - (unsigned long)NULL); + struct xenoprof_counter counter; + + /* Define dom0 as an active domain if not done yet */ + if (!active_defined) { + domid_t domid; + ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL); + if (ret) + goto err; + domid = 0; + ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid); + if (ret) + goto err; + active_defined = 1; + } + + ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL); if (ret) goto err; + for (i=0; i MAX_OPROF_DOMAINS) + return -E2BIG; + + ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL); + if (ret) + return ret; + + for (i=0; i OP_MAX_COUNTER) + num_events = OP_MAX_COUNTER; + + npages = (init.bufsize * nbuf - 1) / PAGE_SIZE + 1; vm_size = npages * PAGE_SIZE; - shared_buffer = (char *) vm_map_xen_pages(result.buf_maddr, - vm_size, prot); + shared_buffer = (char *)vm_map_xen_pages(init.buf_maddr, + vm_size, prot); if (!shared_buffer) { ret = -ENOMEM; goto out; } for (i=0; i< nbuf; i++) { - buf = (xenoprof_buf_t*) - &shared_buffer[i * result.bufsize]; + buf = (struct xenoprof_buf*) + &shared_buffer[i * init.bufsize]; BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS); xenoprof_buf[buf->vcpu_id] = buf; } /* cpu_type is detected by Xen */ cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0; - strncpy(cpu_type, result.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1); + strncpy(cpu_type, init.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1); xenoprof_ops.cpu_type = cpu_type; init_driverfs(); @@ -371,6 +417,8 @@ int __init oprofile_arch_init(struct oprofile_operations * ops) for (i=0; i #include #include @@ -12,7 +13,7 @@ /* Limit amount of pages used for shared buffer (per domain) */ #define MAX_OPROF_SHARED_PAGES 32 -int active_domains[MAX_OPROF_DOMAINS]; +domid_t active_domains[MAX_OPROF_DOMAINS]; int active_ready[MAX_OPROF_DOMAINS]; unsigned int adomains; unsigned int activated; @@ -84,7 +85,8 @@ static void xenoprof_reset_buf(struct domain *d) int active_index(struct domain *d) { - int i, id = d->domain_id; + int i; + domid_t id = d->domain_id; for ( i = 0; i < adomains; i++ ) if ( active_domains[i] == id ) @@ -137,13 +139,11 @@ int reset_active(struct domain *d) return 0; } -int set_active_domains(int num) +int reset_active_list(void) { - int primary; int i; struct domain *d; - /* Reset any existing active domains from previous runs. */ for ( i = 0; i < adomains; i++ ) { if ( active_ready[i] ) @@ -157,24 +157,20 @@ int set_active_domains(int num) } } - adomains = num; + adomains = 0; + activated = 0; - /* Add primary profiler to list of active domains if not there yet */ - primary = active_index(primary_profiler); - if ( primary == -1 ) - { - /* Return if there is no space left on list. */ - if ( num >= MAX_OPROF_DOMAINS ) - return -E2BIG; - active_domains[num] = primary_profiler->domain_id; - num++; - } + return 0; +} - adomains = num; - activated = 0; +int add_active_list (domid_t domid) +{ + if ( adomains >= MAX_OPROF_DOMAINS ) + return -E2BIG; - for ( i = 0; i < adomains; i++ ) - active_ready[i] = 0; + active_domains[adomains] = domid; + active_ready[adomains] = 0; + adomains++; return 0; } @@ -353,26 +349,31 @@ void free_xenoprof_pages(struct domain *d) d->xenoprof = NULL; } -int xenoprof_init(int max_samples, xenoprof_init_result_t *init_result) +int xenoprof_op_init(GUEST_HANDLE(void) arg) { - xenoprof_init_result_t result; + struct xenoprof_init xenoprof_init; int is_primary, num_events; struct domain *d = current->domain; int ret; - ret = nmi_init(&num_events, &is_primary, result.cpu_type); - if ( is_primary ) - primary_profiler = current->domain; + if ( copy_from_guest(&xenoprof_init, arg, 1) ) + return -EFAULT; + ret = nmi_init(&num_events, + &is_primary, + xenoprof_init.cpu_type); if ( ret < 0 ) goto err; + if ( is_primary ) + primary_profiler = current->domain; + /* * We allocate xenoprof struct and buffers only at first time xenoprof_init * is called. Memory is then kept until domain is destroyed. */ if ( (d->xenoprof == NULL) && - ((ret = alloc_xenoprof_struct(d, max_samples)) < 0) ) + ((ret = alloc_xenoprof_struct(d, xenoprof_init.max_samples)) < 0) ) goto err; xenoprof_reset_buf(d); @@ -381,13 +382,13 @@ int xenoprof_init(int max_samples, xenoprof_init_result_t *init_result) d->xenoprof->domain_ready = 0; d->xenoprof->is_primary = is_primary; - result.is_primary = is_primary; - result.num_events = num_events; - result.nbuf = d->xenoprof->nbuf; - result.bufsize = d->xenoprof->bufsize; - result.buf_maddr = __pa(d->xenoprof->rawbuf); + xenoprof_init.is_primary = is_primary; + xenoprof_init.num_events = num_events; + xenoprof_init.nbuf = d->xenoprof->nbuf; + xenoprof_init.bufsize = d->xenoprof->bufsize; + xenoprof_init.buf_maddr = __pa(d->xenoprof->rawbuf); - if ( copy_to_user((void *)init_result, (void *)&result, sizeof(result)) ) + if ( copy_to_guest(arg, &xenoprof_init, 1) ) { ret = -EFAULT; goto err; @@ -409,7 +410,7 @@ int xenoprof_init(int max_samples, xenoprof_init_result_t *init_result) || (op == XENOPROF_release_counters) \ || (op == XENOPROF_shutdown)) -int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) +int do_xenoprof_op(int op, GUEST_HANDLE(void) arg) { int ret = 0; @@ -423,20 +424,24 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) switch ( op ) { case XENOPROF_init: - ret = xenoprof_init((int)arg1, (xenoprof_init_result_t *)arg2); + ret = xenoprof_op_init(arg); break; + case XENOPROF_reset_active_list: + { + ret = reset_active_list(); + break; + } case XENOPROF_set_active: + { + domid_t domid; if ( xenoprof_state != XENOPROF_IDLE ) return -EPERM; - if ( arg2 > MAX_OPROF_DOMAINS ) - return -E2BIG; - if ( copy_from_user((void *)&active_domains, - (void *)arg1, arg2*sizeof(int)) ) + if ( copy_from_guest(&domid, arg, 1) ) return -EFAULT; - ret = set_active_domains(arg2); + ret = add_active_list(domid); break; - + } case XENOPROF_reserve_counters: if ( xenoprof_state != XENOPROF_IDLE ) return -EPERM; @@ -445,15 +450,34 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) xenoprof_state = XENOPROF_COUNTERS_RESERVED; break; - case XENOPROF_setup_events: + case XENOPROF_counter: + { + struct xenoprof_counter counter; if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED ) return -EPERM; if ( adomains == 0 ) - set_active_domains(0); + return -EPERM; - if ( copy_from_user((void *)&counter_config, (void *)arg1, - arg2 * sizeof(struct op_counter_config)) ) + if ( copy_from_guest(&counter, arg, 1) ) return -EFAULT; + + if ( counter.ind > OP_MAX_COUNTER ) + return -E2BIG; + + counter_config[counter.ind].count = (unsigned long) counter.count; + counter_config[counter.ind].enabled = (unsigned long) counter.enabled; + counter_config[counter.ind].event = (unsigned long) counter.event; + counter_config[counter.ind].kernel = (unsigned long) counter.kernel; + counter_config[counter.ind].user = (unsigned long) counter.user; + counter_config[counter.ind].unit_mask = (unsigned long) counter.unit_mask; + + ret = 0; + break; + } + + case XENOPROF_setup_events: + if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED ) + return -EPERM; ret = nmi_setup_events(); if ( !ret ) xenoprof_state = XENOPROF_READY; @@ -526,3 +550,13 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2) return ret; } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index 79689d65be..1c1cf83901 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -682,7 +682,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_nmi_op */ .byte 2 /* do_arch_sched_op */ .byte 2 /* do_callback_op */ /* 30 */ - .byte 3 /* do_xenoprof_op */ + .byte 2 /* do_xenoprof_op */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 266c1c9971..9c27e2a595 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -590,7 +590,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_nmi_op */ .byte 2 /* do_arch_sched_op */ .byte 2 /* do_callback_op */ /* 30 */ - .byte 3 /* do_xenoprof_op */ + .byte 2 /* do_xenoprof_op */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff --git a/xen/include/public/xenoprof.h b/xen/include/public/xenoprof.h index 134df887c4..0699834d5d 100644 --- a/xen/include/public/xenoprof.h +++ b/xen/include/public/xenoprof.h @@ -12,18 +12,22 @@ #define __XEN_PUBLIC_XENOPROF_H__ /* - * Commands to HYPERVISOR_pmc_op(). + * Commands to HYPERVISOR_xenoprof_op(). */ -#define XENOPROF_init 0 -#define XENOPROF_set_active 1 -#define XENOPROF_reserve_counters 3 -#define XENOPROF_setup_events 4 -#define XENOPROF_enable_virq 5 -#define XENOPROF_start 6 -#define XENOPROF_stop 7 -#define XENOPROF_disable_virq 8 -#define XENOPROF_release_counters 9 -#define XENOPROF_shutdown 10 +#define XENOPROF_init 0 +#define XENOPROF_reset_active_list 1 +#define XENOPROF_reset_passive_list 2 +#define XENOPROF_set_active 3 +#define XENOPROF_set_passive 4 +#define XENOPROF_reserve_counters 5 +#define XENOPROF_counter 6 +#define XENOPROF_setup_events 7 +#define XENOPROF_enable_virq 8 +#define XENOPROF_start 9 +#define XENOPROF_stop 10 +#define XENOPROF_disable_virq 11 +#define XENOPROF_release_counters 12 +#define XENOPROF_shutdown 13 #define MAX_OPROF_EVENTS 32 #define MAX_OPROF_DOMAINS 25 @@ -50,25 +54,29 @@ typedef struct xenoprof_buf { } xenoprof_buf_t; DEFINE_GUEST_HANDLE(xenoprof_buf_t); -typedef struct xenoprof_init_result { +typedef struct xenoprof_init { + int32_t max_samples; int32_t num_events; int32_t is_primary; int32_t nbuf; int32_t bufsize; uint64_t buf_maddr; char cpu_type[XENOPROF_CPU_TYPE_SIZE]; -} xenoprof_init_result_t; -DEFINE_GUEST_HANDLE(xenoprof_init_result_t); +} xenoprof_init_t; +DEFINE_GUEST_HANDLE(xenoprof_init_t); + +typedef struct xenoprof_counter { + uint32_t ind; + uint64_t count; + uint32_t enabled; + uint32_t event; + uint32_t hypervisor; + uint32_t kernel; + uint32_t user; + uint64_t unit_mask; +} xenoprof_counter_t; +DEFINE_GUEST_HANDLE(xenoprof_counter_t); -typedef struct xenoprof_counter_config { - unsigned long count; - unsigned long enabled; - unsigned long event; - unsigned long kernel; - unsigned long user; - unsigned long unit_mask; -} xenoprof_counter_config_t; -DEFINE_GUEST_HANDLE(xenoprof_counter_config_t); #endif /* __XEN_PUBLIC_XENOPROF_H__ */ -- 2.30.2